//
//  IMTCANMessageFactory.m
//  ROCOMO
//
//  Created by Kyle Sun on 5/17/16.
//  Copyright © 2016 ROCOMO. All rights reserved.
//

#import "IMTCANMessageFactory.h"
#import "IMTCANR0MessageCoder.h"

@implementation IMTCANMessageFactory

+ (IMTCANMessage *)confirmMessage {
    IMTComfirmParams params = {1, 0, 0};
    return [self messageWithId:0x0f060102 bytes:(Byte *)&params length:sizeof(params) shouldFree:false];
}

+ (IMTCANMessage *)messageWithId:(u_int32_t)cid u32Params:(IMTU32Params)params {
    Byte *bytes = (Byte *)&params;
    return [IMTCANMessageFactory messageWithId:cid bytes:bytes length:kIMTCANMessageStandardDataLength1 shouldFree:NO];
}

+ (IMTCANMessage *)messageWithId:(u_int32_t)cid type:(IMTCarControlType)type {
    IMTU32Params params;
    params.param1 = 0xB2;
    params.param2 = type;
    Byte *bytes = (Byte *)&params;
    return [IMTCANMessageFactory messageWithId:cid bytes:bytes length:kIMTCANMessageStandardDataLength1 shouldFree:NO];
}

+ (IMTCANMessage *)messageWithId:(u_int32_t)cid s32Params:(IMTS32Params)params {
    Byte *bytes = (Byte *)&params;
    return [IMTCANMessageFactory messageWithId:cid bytes:bytes length:kIMTCANMessageStandardDataLength1 shouldFree:NO];
}

+ (IMTCANMessage *)messageWithId:(u_int32_t)cid p2S32Params:(IMTP2S32Params)params {
    Byte *bytes = (Byte *)&params;
    return [IMTCANMessageFactory messageWithId:cid bytes:bytes length:kIMTCANMessageStandardDataLength1 shouldFree:NO];
}


//遥控模式
+ (IMTCANMessage *)messageWithId:(u_int32_t)cid controlParams:(IMTControlParams)params {
    Byte *bytes = (Byte *)&params;
    return [IMTCANMessageFactory messageWithId:cid bytes:bytes length:kIMTCANMessageStandardDataLength1 shouldFree:NO];
}

+ (IMTCANMessage *)messageWithId:(u_int32_t)cid comboParams:(IMTComboParams)params {
    Byte *bytes = (Byte *)&params;
    return [IMTCANMessageFactory messageWithId:cid bytes:bytes length:kIMTCANMessageStandardDataLength1 shouldFree:NO];
}

+ (IMTCANMessage *)messageWithId:(u_int32_t)cid {
    return [IMTCANMessageFactory messageWithId:cid bytes:nil length:kIMTCANMessageStandardDataLength1 shouldFree:NO];
}

+ (IMTCANMessage *)messageWithId:(u_int32_t)cid u32Param:(uint32_t)param {
    u_int64_t params = param;
    Byte *bytes = (Byte *)&params;
    return [IMTCANMessageFactory messageWithId:cid bytes:bytes length:kIMTCANMessageStandardDataLength1 shouldFree:NO];
}

+ (IMTCANMessage *)messageWithId:(u_int32_t)cid u64Param:(uint64_t)param {
    Byte *bytes = (Byte *)&param;
    return [IMTCANMessageFactory messageWithId:cid bytes:bytes length:kIMTCANMessageStandardDataLength1 shouldFree:NO];
}

+ (IMTCANMessage *)messageWithId:(u_int32_t)cid data:(NSData *)data {
    Byte *bytes = malloc(data.length);
    [data getBytes:bytes length:data.length];
    return [IMTCANMessageFactory messageWithId:cid bytes:bytes length:data.length shouldFree:YES];
}

+ (IMTCANMessage *)messageWithId:(u_int32_t)cid boolNum:(BOOL)boolean {
    u_int64_t boolNum;
    if(boolean) {
        boolNum = 0x01;
    } else {
        boolNum = 0x00;
    }
    NSData *data= [NSData dataWithBytes:&boolNum length:8];
    Byte *bytes = malloc(data.length);
    [data getBytes:bytes length:data.length];
    return [IMTCANMessageFactory messageWithId:cid bytes:bytes length:data.length shouldFree:YES];
}

+ (IMTCANMessage *)messageWithId:(u_int32_t)cid data:(NSData *)data forceExtended:(BOOL)force{
    Byte *bytes = malloc(data.length);
    [data getBytes:bytes length:data.length];
    return [IMTCANMessageFactory messageWithId:cid bytes:bytes length:data.length shouldFree:YES forceExtended:(BOOL)force];
}

+ (IMTCANMessage *)messageWithId:(u_int32_t)cid u32Param:(uint32_t)param forceExtended:(BOOL)force{
    Byte *bytes = (Byte *)&param;
    return [IMTCANMessageFactory messageWithId:cid bytes:bytes length:4 shouldFree:NO forceExtended:(BOOL)force];
}

+ (IMTCANMessage *)messageWithId:(u_int32_t)cid bytes:(Byte *)bytes length:(NSInteger)length shouldFree:(BOOL)shouldFree forceExtended:(BOOL)force {
    IMTCANMessageBody body;
    NSData *extra = nil;
    body.cid = cid;
    body.data = length;
    body.length = kIMTCANMessageExtendedDataLength1;
    body.format = CANFormatExtended;
    extra = [NSData dataWithBytes:bytes length:length];
    body.type = CANTypeData;
    body.channel = kIMTCANMessageDefaultChannel;
    
    IMTCANMessage *message = [[IMTCANMessage alloc] initWithBody:body extra:extra];
    
    if (shouldFree) {
        free(bytes);
    }
    return message;
}

+ (IMTCANMessage *)messageWithId:(u_int32_t)cid bytes:(Byte *)bytes length:(NSInteger)length shouldFree:(BOOL)shouldFree {
    
    IMTCANMessageBody body;
    NSData *extra = nil;
    
    body.cid = cid;
    
    if (bytes) {
        if (length <= kIMTCANMessageStandardDataLength1) {
            memcpy(&body.data, bytes, length);
            body.length = length;
            body.format = CANFormatStandard;
        } else {
            body.data = length;
            body.length = kIMTCANMessageExtendedDataLength1;
            body.format = CANFormatExtended;
            extra = [NSData dataWithBytes:bytes length:length];
        }
        body.type = CANTypeData;
    } else {
        body.data = 0;
        body.length = kIMTCANMessageStandardDataLength1;
        body.format = CANFormatStandard;
        body.type = CANTypeRemote;
    }
    
    body.channel = kIMTCANMessageDefaultChannel;
    
    IMTCANMessage *message = [[IMTCANMessage alloc] initWithBody:body extra:extra];
    
    if (shouldFree) {
        free(bytes);
    }
    
    return message;
}

#pragma mark - =======R0相关的=========
+ (IMTCANMessage *)r0_messageWithId:(u_int32_t)cid
                             length:(u_int8_t)length
                             isRead:(BOOL)isRead {
    
    IMTCANMessageBody body;
    body.length = length;//要读取的数据长度
    body.cid = cid;
    NSData * data = [IMTCANR0MessageCoder dataWithMessageID:cid length:length isRead:isRead];
    IMTCANMessage *message = [[IMTCANMessage alloc] initWithBody:body extra:data];
    return message;
}

+ (IMTCANMessage *)r0_messageShortWithId:(u_int32_t)cid
                                    data:(unsigned char *)writeData
                             length:(u_int8_t)length{
    
    IMTCANMessageBody body;
    body.length = length;//要读取的数据长度
    body.cid = cid;
    NSData * data = [IMTCANR0MessageCoder dataWithMessageID:cid withData:writeData length:length];
    IMTCANMessage *message = [[IMTCANMessage alloc] initWithBody:body extra:data];
    return message;
}

+ (IMTCANMessage *)r0_messageDataNumWithId:(u_int32_t)cid
                                      data:(int)writeDataNum
                                    length:(u_int8_t)length{
    IMTCANMessageBody body;
    body.length = length;//要读取的数据长度
    body.cid = cid;
    
    unsigned char * writeData = [IMTCANMessageFactory dataWithInt:writeDataNum andLength:length];
    
    NSData * data = [IMTCANR0MessageCoder dataWithIAPCMD:0x07 MessageID:0 withData:writeData length:length];
    IMTCANMessage *message = [[IMTCANMessage alloc] initWithBody:body extra:data];
    return message;
}

+ (IMTCANMessage *)r0_messageIAPDataNumWithId:(u_int32_t)cid
                                         data:(int)writeDataNum
                                       length:(u_int8_t)length toDevice:(BOOL)isble {
    IMTCANMessageBody body;
    body.length = length;//要读取的数据长度
    body.cid = cid;
    
    unsigned char * writeData = [IMTCANMessageFactory dataWithInt:writeDataNum andLength:length];
    NSData * data = [IMTCANR0MessageCoder dataToDeviceWithIAPCMD:0x07 MessageID:0 withData:writeData length:length toDevice:isble];
    IMTCANMessage *message = [[IMTCANMessage alloc] initWithBody:body extra:data];
    return message;

}

/*
 * msgType 1 IAP准备；2 开始写入IAP数据；3 数据校验；4 IAP完成指令
 * cid 消息的key --- msgtype = 2时 cid为数据包序号，其他时为命令编码cmd
 * msgType 1 IAP准备；2 开始写入IAP数据；3 数据校验；4 IAP完成指令

 */
+ (IMTCANMessage *)r0_messageIAPDataWithId:(u_int32_t)cid
                                      data:(NSData *)writeData
                                   msgType:(uint8_t)msgType
                                    length:(u_int8_t)length toDevice:(BOOL)isble{
    IMTCANMessageBody body;
    body.length = length; // 要读取的数据长度
    body.cid = cid%256; // 升级发送数据包时，包序号用拓展ID表示，拓展ID占一个字节所以超了ff后要重新从0开始
    
    unsigned char cmd;

    if (msgType == 1) {
        cmd = 0x07;
    }else if (msgType == 2){
        cmd = 0x08;
    }else if (msgType == 3){
        cmd = 0x09;
    }else if (msgType == 4){
        cmd = 0x0a;
    }else {
        cmd = 0x01;
    }
    
    Byte *bytes = malloc(writeData.length);
    [writeData getBytes:bytes length:writeData.length];

//    NSData * data = [IMTCANR0MessageCoder dataWithIAPCMD:cmd MessageID:cid withData:bytes length:length]; /// 旧方法
    NSLog(@"生成固件升级消息🌹cmd:%d -----------🌹------ cid:%u -------🌹-------- msgtype:%hhu",cmd,cid,msgType);
    NSData *data = [IMTCANR0MessageCoder dataWithIAPCMD:cmd toDevice:isble MessageID:body.cid withData:bytes length:length];
    IMTCANMessage *message = [[IMTCANMessage alloc] initWithBody:body extra:data];
    return message;
}


//// R0故障检测
+ (IMTCANMessage *)R0_messageDetectionWithId:(u_int32_t)cid
                                        data:(int)writeDataNum
                                      length:(u_int8_t)length{
    IMTCANMessageBody body;
    body.length = length;//要读取的数据长度
    body.cid = cid;
    unsigned char cmd; //madekunsilezenme
    cmd = 0x05; /// 故障检测
    unsigned char * writeData = [IMTCANMessageFactory dataWithInt:writeDataNum andLength:length];
//    Byte *bytes = malloc(writeData.length);
//    [writeData getBytes:bytes length:writeData.length];
    NSData * data = [IMTCANR0MessageCoder dataWithIAPCMD:cmd MessageID:cid withData:writeData length:length];
    IMTCANMessage *message = [[IMTCANMessage alloc] initWithBody:body extra:data];
    return message;
}

/// r0故障检测
+(IMTCANMessage *)R0_DetectionMessageWithIndex:(u_int32_t)index length:(u_int32_t)length {
    
    IMTCANMessageBody body;
    body.length = length;//要读取的数据长度
    Byte * writeData = [IMTCANMessageFactory dataWithInt:index andLength:2] ;
    body.cid = writeData[0];
    Byte *bytes = malloc(2);
    bytes[0] = writeData[1];
    bytes[1] = 0x08;
    unsigned char cmd;
    cmd = 0x05; /// 故障检测
    NSData * data = [IMTCANR0MessageCoder dataWithIAPCMD:cmd MessageID:body.cid withData:bytes length:length];
    IMTCANMessage *message = [[IMTCANMessage alloc] initWithBody:body extra:data];
    return message;
}

+ (Byte *)dataWithInt:(int)num andLength:(int)length{
    Byte *bytes = (Byte *)malloc(length);
    for (int i = 0; i < length; i++) {
        bytes[length - i - 1] = ((num>>((length - i - 1) *8))&0xFF);
    }
    
    return bytes;
}

@end

